//
// @Auther: by wujehy 
// @Email:wujehy@qq.com
// @Data:20-4-14
// @Time:下午2:36
//



#include <handy/logging.h>
#include "UserDataBaseFactory.h"
#include "Business/internaltypes.h"

using namespace handy;

UserDataBaseFactory::UserDataBaseFactory(SQLite::Database *mDb)
{
    if (mDb == nullptr)
    {
        // 错误
        m_Db = nullptr;
    } else
    {
        // 成功 则储存
        m_Db = mDb;
    }
}

/**
 * 表结构
 *
 *
 *
 * @return
 */
int UserDataBaseFactory::initUserTable()
{
    info( "UserDataBaseFactory::initUserTable enter ... " );
    if (m_Db == nullptr)
    {
        info( "UserDataBaseFactory::initUserTable  m_Db == nullptr ... " );
        return ERROR_FAIL;
    }

    // 创建 表
    try
    {
        const bool bExists = m_Db->tableExists( "userinfo" );
        info( "SQLite table 'userinfo' exists=%d ", bExists );

        if (!bExists)
        {

            int ret = m_Db->exec( "CREATE TABLE `userinfo` ("
                                  " `uid` INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT ,"
                                  " `username` TEXT NOT NULL, "
                                  " `password` TEXT NOT NULL, "
                                  " `email` TEXT NOT NULL, "
                                  " `createat` INTEGER NOT NULL, "
                                  " `modifyat` INTEGER NOT NULL "
                                  ");" );

            m_Db->exec( "CREATE INDEX `userinfo_idx` ON `userinfo` (`username`)" );

            info( "SignalDataBaseFactory::initSignalkeypairsTable() ret=%d", ret );
            return ERROR_SUCCESS;


        } else
        {
            // 存在 直接返回成功
            return ERROR_SUCCESS;
        }


    } catch (std::exception &e)
    {
        debug( " SignalDataBaseFactory::initUserTable , SQLite exception: %d", e.what());
        return ERROR_FAIL;
    }
}

int UserDataBaseFactory::insertUser(std::string &username, std::string &passwordMd5, std::string &email)
{
    info( "UserDataBaseFactory::insertUser enter ... " );
    if (m_Db == nullptr)
    {
        info( "UserDataBaseFactory::insertUser  m_Db == nullptr ... " );
        return ERROR_FAIL;
    }

    try
    {
        // TODO
        std::string sql = "insert into `userinfo` (`username`, `password`, `email`, `createat`, `modifyat`) "
                          "values (?, ? , ? , ? , ?);";
        SQLite::Statement query( *m_Db, sql );

        int64_t currTime = util::timeMilli();
        query.bind( 1, username );
        query.bind( 2, passwordMd5 );
        query.bind( 3, email );
        query.bind( 4, currTime );
        query.bind( 5, currTime );
        int nb = query.exec();
        debug( "UserDataBaseFactory::insertUser   : nb =%d", nb );
        if (nb > 0)
        {
            // 影响 1 条以上 才成功,否则是失败
            return ERROR_SUCCESS;
        } else
        {
            return ERROR_FAIL;
        }

    } catch (std::exception &e)
    {
        debug( " SignalDataBaseFactory::insertUser , SQLite exception: %d", e.what());
        return ERROR_FAIL;
    }
}

int UserDataBaseFactory::existUser(std::string &username)
{
    info( "UserDataBaseFactory::existUser enter ... " );
    if (m_Db == nullptr)
    {
        info( "UserDataBaseFactory::existUser  m_Db == nullptr ... " );
        return ERROR_FAIL;
    }

    try
    {
        // TODO
        std::string sql = "select * from userinfo where username = ? ;";
        SQLite::Statement query( *m_Db, sql );
        query.bind( 1, username );


        int nb = 0;
        if (query.executeStep())
        {
            nb = query.getColumnCount();
        }

        info( "UserDataBaseFactory::existUser , nb = %d ", nb );
        if (nb > 0)
        {
            return ERROR_SUCCESS;
        } else
        {
            return ERROR_FAIL;
        }

    } catch (std::exception &e)
    {
        debug( " SignalDataBaseFactory::existUser , SQLite exception: %d", e.what());
        return ERROR_FAIL;
    }
}

int UserDataBaseFactory::checktUser(std::string &username, std::string &passwordmd5, std::string email)
{
    info( "UserDataBaseFactory::checktUser enter ... " );
    if (m_Db == nullptr)
    {
        info( "UserDataBaseFactory::checktUser  m_Db == nullptr ... " );
        return ERROR_FAIL;
    }

    try
    {
        // TODO
        std::string sql;
        if (username.empty() && !email.empty())
        {
            sql = "select * from userinfo where email = ?  and `password` = ?;";
        } else
        {
            sql = "select * from userinfo where username = ?  and `password` = ?;";
        }
        SQLite::Statement query( *m_Db, sql );

        if (username.empty() && !email.empty())
        {
            query.bind( 1, email );
        } else
        {
            query.bind( 1, username );
        }

        query.bind( 2, passwordmd5 );
        int nb = 0;
        if (query.executeStep())
        {
            nb = query.getColumnCount();
        }

        info( "UserDataBaseFactory::checktUser , nb = %d ", nb );
        if (nb > 0)
        {
            return ERROR_SUCCESS;
        } else
        {
            return ERROR_FAIL;
        }

    } catch (std::exception &e)
    {
        debug( " SignalDataBaseFactory::checktUser , SQLite exception: %d", e.what());
        return ERROR_FAIL;
    }
}

int UserDataBaseFactory::addUser(std::string &username, std::string &passwordMd5, std::string &email)
{
    if (existUser( username ) == ERROR_FAIL)
    {
        info( "UserDataBaseFactory::addUser , user is empty" );
        return insertUser( username, passwordMd5, email );
    } else
    {
        info( "UserDataBaseFactory::addUser , user find " );
        return ERROR_FAIL;
    }
}

int UserDataBaseFactory::updataPassword(std::string &username, std::string &oldpasswordMd5, std::string &newPasswordMd5)
{
    info( "UserDataBaseFactory::updataPassword enter ... " );
    if (m_Db == nullptr)
    {
        info( "UserDataBaseFactory::updataPassword  m_Db == nullptr ... " );
        return ERROR_FAIL;
    }

    try
    {
        // TODO
        std::string sql = "update userinfo "
                          "set `password` = ? "
                          "where username = ? and `password` = ?;";
        SQLite::Statement query( *m_Db, sql );
        query.bind( 1, newPasswordMd5 );
        query.bind( 2, username );
        query.bind( 3, oldpasswordMd5 );

        int nb = query.exec();
        debug( "UserDataBaseFactory::updataPassword   : nb =%d", nb );
        if (nb > 0)
        {
            // 影响 1 条以上 才成功,否则是失败
            return ERROR_SUCCESS;
        } else
        {
            return ERROR_FAIL;
        }

    } catch (std::exception &e)
    {
        debug( " SignalDataBaseFactory::updataPassword , SQLite exception: %d", e.what());
        return ERROR_FAIL;
    }
    return 0;
}

int64_t UserDataBaseFactory::getUidByUsername(std::string &username)
{
    info( "UserDataBaseFactory::getUidByUsername enter ... " );
    if (m_Db == nullptr)
    {
        info( "UserDataBaseFactory::getUidByUsername  m_Db == nullptr ... " );
        return ERROR_FAIL;
    }

    try
    {
        // TODO
        std::string sql = "select uid from userinfo where username = ?;";
        SQLite::Statement query( *m_Db, sql );
        query.bind( 1, username );
        int64_t uid = 0;
        if (query.executeStep())
        {
            uid = query.getColumn( 0 ).getInt64();
        }
        debug( "UserDataBaseFactory::getUidByUsername  : uid = %d", uid );

        return uid;
    } catch (std::exception &e)
    {
        debug( " SignalDataBaseFactory::getUidByUsername , SQLite exception: %d", e.what());
        return ERROR_FAIL;
    }
    return 0;
}

int UserDataBaseFactory::changePassword(std::string &username, std::string &newPassword)
{
    info( "UserDataBaseFactory::changePassword enter ... " );
    if (m_Db == nullptr)
    {
        info( "UserDataBaseFactory::changePassword  m_Db == nullptr ... " );
        return ERROR_FAIL;
    }

    try
    {
        // TODO
        std::string sql = "update userinfo "
                          "set `password` = ? "
                          "where username = ? ;";
        SQLite::Statement query( *m_Db, sql );
        query.bind( 1, newPassword );
        query.bind( 2, username );

        int nb = query.exec();
        debug( "UserDataBaseFactory::changePassword   : nb =%d", nb );
        if (nb > 0)
        {
            // 影响 1 条以上 才成功,否则是失败
            return ERROR_SUCCESS;
        } else
        {
            return ERROR_FAIL;
        }

    } catch (std::exception &e)
    {
        debug( " SignalDataBaseFactory::changePassword , SQLite exception: %d", e.what());
        return ERROR_FAIL;
    }
    return 0;
}

//info("UserDataBaseFactory::checktUser enter ... ");
//if (m_Db == nullptr)
//{
//info("UserDataBaseFactory::checktUser  m_Db == nullptr ... ");
//return ERROR_FAIL;
//}
//
//try
//{
//// TODO
//
//} catch (std::exception &e)
//{
//debug(" SignalDataBaseFactory::checktUser , SQLite exception: %d", e.what());
//return ERROR_FAIL;
//}
//return 0;